In [2]:
import numpy as np
Create two very long NumPy arrays x
and y
and sum the arrays using:
z = x + y
; andfor
loop that computes the sum entry-by-entryCompare the time required for the two approaches for vectors of different lengths. The values of the array entries are not important for this test.
Hint: To loop over an array using indices, try a construction like:
x = np.ones(100)
y = np.ones(len(x))
for i in range(len(x)):
print(x[i]*y[i])
Timing NumPy addition for 1 million elements arrays
In [2]:
n = 1000000
x = np.random.rand(n)
y = np.random.rand(n)
%time z = x + y
Timing 1 million elements arrays addition using an entry-by-entry function
In [3]:
def sum_vec(x, y):
"Sum two vectors entry by entry"
z = np.zeros(n)
for i in range(n):
z[i] = x[i] + y[i]
return z
%time w = sum_vec(x, y)
Anonymised scores (out of 60) for an examination are stored in a NumPy array. Write:
scores.sort()
, where scores
is a NumPy array holding the scores).min
', 'max
' and 'mean
'. Use the NumPy array functions min()
, max()
and mean()
to do the
computation, e.g. max = scores.max()
.Use the scores
scores = np.array([58.0, 35.0, 24.0, 42, 7.8])
In [4]:
# Test scores
scores = np.array([58.0, 35.0, 24.0, 42, 7.8])
In [5]:
def percentages(scores):
"Calculate percentages (max score = 60) from a list of scores and returns them sorted"
sorted_scores = scores / 60
sorted_scores.sort()
return sorted_scores
print(percentages(scores))
In [6]:
def max_min_mean(scores):
"Return a dictionary with max, min and mean score from a list of scores"
out = {}
out['min'] = scores.min()
out['max'] = scores.max()
out['mean'] = scores.mean()
return out
print(max_min_mean(scores))
In [7]:
def max_min_mean2(scores, exclude_extreme):
"Return a dictionary with max, min and mean score from a list of scores excluding extremes if exclude_extreme = 1"
out = {}
# If extremes are excluded filter the sorted list from second to second to last element
if exclude_extreme == 1:
scores.sort()
scores_filtered = scores[1:-1]
# Else use the entire list
elif exclude_extreme == 0:
scores_filtered = scores
# If exclude_extreme is not 0 nor 1 return a message
else:
return 'The second parameter should be either 0 (to include extremes) or 1 (to exclude them)'
out['min'] = scores_filtered.min()
out['max'] = scores_filtered.max()
out['mean'] = scores_filtered.mean()
return out
print(max_min_mean2(scores, 1))
In [8]:
A = np.array([[4.0, 7.0, -2.43, 67.1],
[-4.0, 64.0, 54.7, -3.33],
[2.43, 23.2, 3.64, 4.11],
[1.2, 2.5, -113.2, 323.22]])
print(A)
use array slicing to
Print the results to the screen to check. Try to use array slicing such that your code would still work if the dimensions of A
were enlarged.
Also, compute the tranpose of A
(search online to find the function/syntax to do this).
Third column as a 1D array
In [9]:
print(A[:,2])
First two rows as a 2D sub-array
In [10]:
print(A[:2,:])
Bottom right $2 \times 2$ block as a 2D sub-array
In [11]:
print(A[-2:,-2:])
Sum of the last column
In [12]:
print(A[:,-1].sum())
Transpose of A
In [13]:
print(A.transpose())
In a previous exercise you implemented the bisection algorithm to find approximate roots of a mathematical function. Use the SciPy bisection function optimize.bisect
(http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.optimize.bisect.html) to find roots of the mathematical function that was used in the previous exercise. Compare the results computed by SciPy and your program from the earlier exercise, and compare the computational time (using %time
).
In [3]:
def f(x):
return x**3 - 6*x**2 + 4*x + 12
#return x**2 + x - 20 # Roots = -5, 4
In [6]:
def compute_root(f, x0, x1, tol, max_it):
"""Computes the root of f between x0 and x1 using bisection,
stops if the value of f at the root is under tol or if max_it is reached
and returns the root, the value of f at the root and the number of iterations"""
for i in range(max_it):
# Compute x_mid
x_mid = (x0 + x1) / 2
# Compute f for the three values
f_0, f_1, f_mid = f(x0), f(x1), f(x_mid)
# Check the value of f_0*f_mid to determine how to update the endpoints
if f_0*f_mid < 0:
x1 = x_mid
else:
x0 = x_mid
# Check if f is under tol
if abs(f_mid) < tol:
return x_mid, f_mid, i+1
# Return the approximate root in case max_it is reached
return x_mid, f_mid, i+1
# Test for the function f
%time x, f_x, num_it = compute_root(f, x0=3, x1=6, tol=1.0e-6, max_it=1000)
print('Approximate root:', x)
print('Value of f:', f_x)
print('Number of iterations:', num_it)
Below we compute the same root using scipy function bisect: the wall time for both functions is very low but the scipy function is considerably better:
In [7]:
from scipy.optimize import bisect as bisect
# Compute the root of f using scipy function
%time x0 = bisect(f, a=3, b=6)
print('Approximate root:', x0)
print('Value of f:', f(x0))